www.gusucode.com > VC++ 树控节点及颜色调整程序-源码程序 > VC++ 树控节点及颜色调整程序-源码程序/code/mtreectl.cpp
// MyTreeCtrl.cpp : implementation file // Download by http://www.NewXing.com // This is a part of the Microsoft Foundation Classes C++ library. // Copyright (C) 1992-1998 Microsoft Corporation // All rights reserved. // // This source code is only intended as a supplement to the // Microsoft Foundation Classes Reference and related // electronic documentation provided with the library. // See these sources for detailed information regarding the // Microsoft Foundation Classes product. #include "stdafx.h" #include "CmnCtrl1.h" #include "mtreectl.h" #include "treecpg.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // CMyTreeCtrl CMyTreeCtrl::CMyTreeCtrl() { m_bDragging = FALSE; m_pimagelist = NULL; } CMyTreeCtrl::~CMyTreeCtrl() { } BEGIN_MESSAGE_MAP(CMyTreeCtrl, CTreeCtrl) //{{AFX_MSG_MAP(CMyTreeCtrl) ON_NOTIFY_REFLECT(TVN_ENDLABELEDIT, OnEndLabelEdit) ON_NOTIFY_REFLECT(TVN_BEGINDRAG, OnBeginDrag) ON_WM_MOUSEMOVE() ON_WM_LBUTTONUP() ON_WM_RBUTTONUP() ON_WM_DESTROY() ON_WM_ERASEBKGND() ON_NOTIFY_REFLECT(TVN_BEGINRDRAG, OnBeginDrag) ON_WM_PAINT() //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CMyTreeCtrl message handlers void CMyTreeCtrl::OnDestroy() { CImageList *pimagelist; pimagelist = GetImageList(TVSIL_NORMAL); pimagelist->DeleteImageList(); delete pimagelist; } void CMyTreeCtrl::SetNewStyle(long lStyleMask, BOOL bSetBits) { long lStyleOld; lStyleOld = GetWindowLong(m_hWnd, GWL_STYLE); lStyleOld &= ~lStyleMask; if (bSetBits) lStyleOld |= lStyleMask; SetWindowLong(m_hWnd, GWL_STYLE, lStyleOld); SetWindowPos(NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER); } void CMyTreeCtrl::OnEndLabelEdit(LPNMHDR pnmhdr, LRESULT *pLResult) { TV_DISPINFO *ptvinfo; ((CTreeCtrlPage *)GetParent())->ShowNotification(pnmhdr, pLResult); ptvinfo = (TV_DISPINFO *)pnmhdr; if (ptvinfo->item.pszText != NULL) { ptvinfo->item.mask = TVIF_TEXT; SetItem(&ptvinfo->item); } *pLResult = TRUE; } void CMyTreeCtrl::OnMouseMove(UINT nFlags, CPoint point) { HTREEITEM hitem; UINT flags; if (m_bDragging) { ASSERT(m_pimagelist != NULL); m_pimagelist->DragMove(point); if ((hitem = HitTest(point, &flags)) != NULL) { m_pimagelist->DragLeave(this); SelectDropTarget(hitem); m_hitemDrop = hitem; m_pimagelist->DragEnter(this, point); } } CTreeCtrl::OnMouseMove(nFlags, point); } BOOL CMyTreeCtrl::IsChildNodeOf(HTREEITEM hitemChild, HTREEITEM hitemSuspectedParent) { do { if (hitemChild == hitemSuspectedParent) break; } while ((hitemChild = GetParentItem(hitemChild)) != NULL); return (hitemChild != NULL); } BOOL CMyTreeCtrl::TransferItem(HTREEITEM hitemDrag, HTREEITEM hitemDrop) { TV_INSERTSTRUCT tvstruct; TCHAR sztBuffer[50]; HTREEITEM hNewItem, hFirstChild; // avoid an infinite recursion situation tvstruct.item.hItem = hitemDrag; tvstruct.item.cchTextMax = 49; tvstruct.item.pszText = sztBuffer; tvstruct.item.mask = TVIF_CHILDREN | TVIF_HANDLE | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_TEXT; GetItem(&tvstruct.item); // get information of the dragged element tvstruct.hParent = hitemDrop; tvstruct.hInsertAfter = TVI_SORT; tvstruct.item.mask = TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_TEXT; hNewItem = InsertItem(&tvstruct); while ((hFirstChild = GetChildItem(hitemDrag)) != NULL) { TransferItem(hFirstChild, hNewItem); // recursively transfer all the items DeleteItem(hFirstChild); // delete the first child and all its children } return TRUE; } void CMyTreeCtrl::OnButtonUp() { if (m_bDragging) { ASSERT(m_pimagelist != NULL); m_pimagelist->DragLeave(this); m_pimagelist->EndDrag(); delete m_pimagelist; m_pimagelist = NULL; if (m_hitemDrag != m_hitemDrop && !IsChildNodeOf(m_hitemDrop, m_hitemDrag) && GetParentItem(m_hitemDrag) != m_hitemDrop) { TransferItem(m_hitemDrag, m_hitemDrop); DeleteItem(m_hitemDrag); } else MessageBeep(0); ReleaseCapture(); m_bDragging = FALSE; SelectDropTarget(NULL); } } void CMyTreeCtrl::OnLButtonUp(UINT nFlags, CPoint point) { OnButtonUp(); CTreeCtrl::OnLButtonUp(nFlags, point); } void CMyTreeCtrl::OnRButtonUp(UINT nFlags, CPoint point) { OnButtonUp(); CTreeCtrl::OnRButtonUp(nFlags, point); } void CMyTreeCtrl::OnBeginDrag(LPNMHDR pnmhdr, LRESULT *pLResult) { CPoint ptAction; UINT nFlags; GetCursorPos(&ptAction); ScreenToClient(&ptAction); ((CTreeCtrlPage *)GetParent())->ShowNotification(pnmhdr, pLResult); ASSERT(!m_bDragging); m_bDragging = TRUE; m_hitemDrag = HitTest(ptAction, &nFlags); m_hitemDrop = NULL; ASSERT(m_pimagelist == NULL); m_pimagelist = CreateDragImage(m_hitemDrag); // get the image list for dragging m_pimagelist->DragShowNolock(TRUE); m_pimagelist->SetDragCursorImage(0, CPoint(0, 0)); m_pimagelist->BeginDrag(0, CPoint(0,0)); m_pimagelist->DragMove(ptAction); m_pimagelist->DragEnter(this, ptAction); SetCapture(); } BOOL CMyTreeCtrl::OnEraseBkgnd(CDC* pDC) { return TRUE; //return CTreeCtrl::OnEraseBkgnd(pDC); } /* void CMyTreeCtrl::OnPaint() { CPaintDC dc(this); // device context for painting // 创建一个和显示DC相容的内存DC CDC memDC; memDC.CreateCompatibleDC( &dc ); CRect rcClient; //得到控件的尺寸大小 GetClientRect(&rcClient); // 创建一个和显示DC配置一样的内存DC CBitmap bitmap; bitmap.CreateCompatibleBitmap( &dc, rcClient.Width(), rcClient.Height() ); memDC.SelectObject( &bitmap ); // 在内存中创建需要刷新部分的区域 CRgn rgn; rgn.CreateRectRgnIndirect( &rcClient); memDC.SelectClipRgn(&rgn); rgn.DeleteObject(); // 让控件作完它缺省要绘制的东西 CWnd::DefWindowProc( WM_PAINT, (WPARAM)memDC.m_hDC, 0 ); // 创建一个MASK DC CDC maskDC; maskDC.CreateCompatibleDC(&dc); CBitmap maskBitmap; // 用CBitmap类中的成员函数CreateBitmap创建一个位图,函数原形如下 //BOOL CreateBitmap( int nWidth, int nHeight, UINT nPlanes, UINT nBitcount, const void* lpBits ); //相关参数 //nWidth表示位图的宽度 //nHeight表示位图的高度 //nPlanes表示位图的色彩平面数目 //nBitcount表示每一点显示的颜色位数,也就是说每一个点,需要用多少位来显示 //lpBits指向一个数组,该数组包含了最初的位图位值,如果是NULL的话,新的位图就不被初始化 //所以下面一行代码创建了一个单色的位图 maskBitmap.CreateBitmap( rcClient.Width(), rcClient.Height(), 1, 1, NULL ); maskDC.SelectObject( &maskBitmap ); //maskDC选择该位图 memDC.SetBkColor( ::GetSysColor( COLOR_WINDOW ) ); //设置DC的背景颜色 // 把内存DC中的内容拷贝到mask DC中去,现在maskDC中保存的位图和 //内存DC中的位图内容是一模一样,只是颜色只有黑白两色 maskDC.BitBlt( 0, 0, rcClient.Width(), rcClient.Height(), &memDC, rcClient.left, rcClient.top, SRCCOPY ); // 在内存DC中透明的拷贝图象 //通过下面三行代码,memDC里面的位图的背景搞成都是黑的了,其他图标和文字保持原来的颜色 memDC.SetBkColor(RGB(249,230,196)); memDC.SetTextColor(RGB(255,255,255)); memDC.BitBlt(rcClient.left, rcClient.top, rcClient.Width(), rcClient.Height(), &maskDC, rcClient.left, rcClient.top, SRCAND); dc.BitBlt(rcClient.left, rcClient.top, rcClient.Width(), rcClient.Height(), &memDC, rcClient.left, rcClient.top,SRCCOPY); } */ void CMyTreeCtrl::OnPaint() { CPaintDC dc(this); // device context for painting // 创建一个和显示DC相容的内存DC CDC memDC; memDC.CreateCompatibleDC( &dc ); CRect rcClient; //得到控件的尺寸大小 GetClientRect(&rcClient); // 创建一个和显示DC配置一样的内存DC CBitmap bitmap; bitmap.CreateCompatibleBitmap( &dc, rcClient.Width(), rcClient.Height() ); memDC.SelectObject( &bitmap ); // 在内存中创建需要刷新部分的区域 CRgn rgn; rgn.CreateRectRgnIndirect( &rcClient); memDC.SelectClipRgn(&rgn); rgn.DeleteObject(); // 让控件作完它缺省要绘制的东西 CWnd::DefWindowProc( WM_PAINT, (WPARAM)memDC.m_hDC, 0 ); // 创建一个MASK DC CDC maskDC; maskDC.CreateCompatibleDC(&dc); CBitmap maskBitmap; // 用CBitmap类中的成员函数CreateBitmap创建一个位图,函数原形如下 //BOOL CreateBitmap( int nWidth, int nHeight, UINT nPlanes, UINT nBitcount, const void* lpBits ); //相关参数 //nWidth表示位图的宽度 //nHeight表示位图的高度 //nPlanes表示位图的色彩平面数目 //nBitcount表示每一点显示的颜色位数,也就是说每一个点,需要用多少位来显示 //lpBits指向一个数组,该数组包含了最初的位图位值,如果是NULL的话,新的位图就不被初始化 //所以下面一行代码创建了一个单色的位图 maskBitmap.CreateBitmap( rcClient.Width(), rcClient.Height(), 1, 1, NULL ); maskDC.SelectObject( &maskBitmap ); //maskDC选择该位图 memDC.SetBkColor( ::GetSysColor( COLOR_WINDOW ) ); //设置DC的背景颜色 // 把内存DC中的内容拷贝到mask DC中去,现在maskDC中保存的位图和 //内存DC中的位图内容是一模一样,只是颜色只有黑白两色 maskDC.BitBlt( 0, 0, rcClient.Width(), rcClient.Height(), &memDC, rcClient.left, rcClient.top, SRCCOPY ); //dc.SetBkColor(RGB(249,230,196)); // 在内存DC中透明的拷贝图象 //通过下面三行代码,memDC里面的位图的背景搞成都是黑的了,其他图标和文字保持原来的颜色 memDC.SetBkColor(RGB(0,0,0)); memDC.SetTextColor(RGB(255,255,255)); memDC.BitBlt(rcClient.left, rcClient.top, rcClient.Width(), rcClient.Height(), &maskDC, rcClient.left, rcClient.top, SRCAND); //通过下面三行代码,dc里面的位图的文字背景色搞成黑色,背景保持我们指定的背景颜色 // 用客户指定的颜色来填充控件背景 dc.FillRect(rcClient, &CBrush(RGB(249,230,196))); // dc.SetBkColor(RGB(255,255,255)); //dc.SetTextColor(RGB(0,0,0)); dc.BitBlt(rcClient.left, rcClient.top, rcClient.Width(), rcClient.Height(), &maskDC, rcClient.left, rcClient.top, SRCAND); //把前景和背景相结合,完成树控件中内容的显示 dc.BitBlt(rcClient.left, rcClient.top, rcClient.Width(), rcClient.Height(), &memDC, rcClient.left, rcClient.top,SRCPAINT); }